package cc.rengu.igas.bomp.core.service.trans;

import cc.rengu.igas.bomp.common.enums.RespCodeEnum;
import cc.rengu.igas.bomp.core.service.base.ManageService;
import cc.rengu.igas.bomp.facade.request.UnionRiskMchntQueryRequest;
import cc.rengu.igas.bomp.facade.response.UnionRiskMchntQueryResponse;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.RedisUtil;
import cc.rengu.oltp.utility.util.XmlConfigUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;

import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.HashMap;


public class UnionRiskMchntQueryService extends ManageService {
    @Override
    protected Object bizBeforeCust() throws Exception {
        UnionRiskMchntQueryRequest unionRiskMchntQueryRequest = new UnionRiskMchntQueryRequest();
        ConvertUtil.convertOutput(unionRiskMchntQueryRequest);
        return unionRiskMchntQueryRequest;
    }

    /**
     * 先从缓存查询token，查无token则发起请求生成token存redis，然后使用token查询联防信息
     *
     * @param request 姓名身份证营业执照查询类型
     * @return respJsonString中isInBlackList是否在黑名单列表，三位的位图，取值0或1，
     * 分别代表是否列入风险可疑商户、
     * 是否被国家企业信用信息公示系统列为经营异常、
     * 是否被国家企业信用信息公示系统列入失信黑名单。
     * @throws Exception
     */
    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        UnionRiskMchntQueryRequest unionRiskMchntQueryRequest = (UnionRiskMchntQueryRequest) request;
        String respCode = null;
        String respDesc = null;
        rglog.info("获取到法人姓名<{}>", unionRiskMchntQueryRequest.getArtifName());
        rglog.info("获取到法人身份证号<{}>", unionRiskMchntQueryRequest.getCertNo());
        rglog.info("获取到法人证件类型<{}>", unionRiskMchntQueryRequest.getCertType());
        rglog.info("获取到商户营业执照号<{}>", unionRiskMchntQueryRequest.getLicenceCode());
        rglog.info("获取到查询类型<{}>", unionRiskMchntQueryRequest.getQueryType());

        String url = XmlConfigUtil.getXmlConfigCacheKeyValue("mhsiqs", "url");
        String appId = XmlConfigUtil.getXmlConfigCacheKeyValue("mhsiqs", "appId");
        String appSecret = XmlConfigUtil.getXmlConfigCacheKeyValue("mhsiqs", "appSecret");


        //获取redis的缓存token数据
        String mhstoken = RedisUtil.onceGet("mhstoken");
        rglog.info("从redis缓存中查询token数据<{}>", mhstoken);
        if (mhstoken == null) {
            OkHttpClient httpClient = new OkHttpClient();
            String queryTokenUrl = url + "/upapi/mhsiqs/token?app_id=" + appId + "&app_secret=" + appSecret;
            rglog.info("token值为空，发起生成银联token请求，url:<{}>", queryTokenUrl);
            Request httpRequest = new Request.Builder().url(queryTokenUrl).build();
            Response response = httpClient.newCall(httpRequest).execute();
            String respString = response.body().string();
            rglog.info("银联返回报文:<{}>", respString);
            JSONObject jsonObject = JSONObject.parseObject(respString);
            respCode = jsonObject.getString("respCd");
            respDesc = jsonObject.getString("respDesc");
            if (!"0000".equals(respCode)) {
                throw new BizException(respCode, respDesc);
            }
            mhstoken = jsonObject.getString("token");
            int expire_in = jsonObject.getInteger("expire_in");
            rglog.info("接口返回值token<{}>,有效期<{}>", mhstoken, expire_in);
            if (mhstoken == null) {
                rglog.error("通讯异常，银联查询token接口返回为空");
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
            rglog.info("保存新token到redis缓存，key<mhstoken>-value<{}>,有效期<{}>", mhstoken, expire_in);
            RedisUtil.onceSet("mhstoken", mhstoken, expire_in);
        }

        rglog.info("调用商户共享联防查询,token<{}>", mhstoken);
        String signature = XmlConfigUtil.getXmlConfigCacheKeyValue("mhsiqs", "signature");
        rglog.info("签名信息signature<{}>", signature);
        String ts = Long.toString(System.currentTimeMillis());
        HashMap childMap = new HashMap();
        childMap.put("artifCertifId", "".equals(unionRiskMchntQueryRequest.getCertNo()) ? "" : unionRiskMchntQueryRequest.getCertNo());
        childMap.put("artifNm", "".equals(unionRiskMchntQueryRequest.getArtifName()) ? "" : unionRiskMchntQueryRequest.getArtifName());
        childMap.put("licNo", "".equals(unionRiskMchntQueryRequest.getLicenceCode()) ? "" : unionRiskMchntQueryRequest.getLicenceCode());
        childMap.put("queryTp", unionRiskMchntQueryRequest.getQueryType());
        ArrayList lists = new ArrayList();
        lists.add(childMap);
        HashMap parentMap = new HashMap();
        parentMap.put("list", lists);
        String body = JSONObject.toJSONString(parentMap);
        rglog.info("请求体body<{}>", body);
        String sign = sign(body, ts, signature);
        rglog.info("签名数据sign<{}>", sign);

        OkHttpClient client = new OkHttpClient();
        String queryUrl = url + "/upapi/mhsiqs/query?token=" + mhstoken + "&sign=" + sign + "&ts=" + ts;
        rglog.info("发起查询银联联防商户请求，url:<{}>", queryUrl);
        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
        Request httpRequest = new Request.Builder().url(queryUrl).post(RequestBody.create(mediaType, body)).build();
        Response response = client.newCall(httpRequest).execute();

        String respJsonString = response.body().string();
        rglog.info("商户联防查询响应，respJsonString:<{}>", respJsonString);
        JSONObject jsonObject = JSONObject.parseObject(respJsonString);
        respCode = jsonObject.getString("respCd");
        respDesc = jsonObject.getString("respDesc");
        if (!"0000".equals(respCode)) {
            throw new BizException(respCode, respDesc);
        }
        JSONArray jsonArray = jsonObject.getJSONArray("data");
        JSONObject data = (JSONObject) jsonArray.get(0);
        String isInBlackList = data.getString("isInBlackList");
        BizResponse bizResponse = new BizResponse();
        UnionRiskMchntQueryResponse unionRiskMchntQueryResponse = new UnionRiskMchntQueryResponse();
        unionRiskMchntQueryResponse.setIsInBlackList(isInBlackList);
        unionRiskMchntQueryResponse.setRespJsonString(respJsonString);
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(unionRiskMchntQueryResponse);
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        UnionRiskMchntQueryResponse unionRiskMchntQueryResponse = (UnionRiskMchntQueryResponse) bizResponse.getResult();
        ConvertUtil.convertInput(unionRiskMchntQueryResponse);
    }


    /**
     * 签名算法
     *
     * @param body      报文体
     * @param ts        时间戳
     * @param signature 密钥
     * @return
     */
    public static String sign(String body, String ts, String signature) {
        String sign = encodeBySHA256(signature + body + ts);

        return sign;
    }

    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * encode By SHA-256
     *
     * @param str
     * @return
     */
    public static String encodeBySHA256(String str) {
        if (str == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.reset();
            messageDigest.update(str.getBytes("UTF-8"));
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Takes the raw bytes from the digest and formats them correct.
     *
     * @param bytes the raw bytes from the digest.
     * @return the formatted bytes.
     */
    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;

        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }

        return buf.toString();
    }
}
